#include <iostream>
#include <string.h>
#include <vector>
using std::cout;
using std::endl;
using std::vector;

class String {
public:
    // 构造函数 & 析构函数
    String();
    String(const char* pstr);
    String(const String&);
    ~String();

    // 成员函数
    bool empty() const;
    size_t size() const;
    const char* c_str() const;
    String& append(const String&);
    String& append(const char*);

    // 运算符重载
    String &operator=(const String&);
    String &operator=(const char *);
    String &operator+=(const String &);
    String &operator+=(const char *);

    char &operator[](std::size_t index);
    const char &operator[](std::size_t index) const;

    friend String operator+(const String &, const String &);
    friend String operator+(const String &, const char *);
    friend String operator+(const char *, const String &);

    friend bool operator==(const String &, const String &);
    friend bool operator!=(const String &, const String &);

    friend bool operator<(const String &, const String &);
    friend bool operator>(const String &, const String &);
    friend bool operator<=(const String &, const String &);
    friend bool operator>=(const String &, const String &);

    friend std::ostream &operator<<(std::ostream &os, const String &s);
    friend std::istream &operator>>(std::istream &is, String &s);
private:
    char* _pstr;
};

// 默认构造函数
String::String() 
    : _pstr(new char[1]()) {
        std::cout << "String()" << std::endl;
    }

// 带参构造函数
String::String(const char* pstr) 
    : _pstr(new char[strlen(pstr) + 1]()) {
        strcpy(_pstr, pstr);
        std::cout << "String(const char*)" << std::endl;
    }

// 拷贝构造函数（委托构造）
String::String(const String& rhs) 
    : String(rhs._pstr) {
        std::cout << "String(const String&)" << std::endl;
    }

// 析构函数
String::~String() {
    std::cout << "~String()" << std::endl;
    delete[] _pstr;
    _pstr = nullptr;
}

// 判断空字符串
bool String::empty() const {
    return size() == 0;
}

// 获取字符串长度
size_t String::size() const {
    return strlen(_pstr);
}

// 获取C风格字符串
const char* String::c_str() const {
    return _pstr;
}

// 追加String对象
String& String::append(const String& rhs) {
    const size_t len = size() + rhs.size();
    char* temp = new char[len + 1];
    strcpy(temp, _pstr);
    strcat(temp, rhs._pstr);
    delete[] _pstr;
    _pstr = temp;
    return *this;
}

// 追加C风格字符串
String& String::append(const char* pstr) {
    String temp(pstr);
    return append(temp);
}

// 赋值运算符
String& String::operator=(const String& rhs) {
    if (this != &rhs) {
        delete[] _pstr;
        _pstr = new char[strlen(rhs._pstr) + 1];
        strcpy(_pstr, rhs._pstr);
    }
    return *this;
}

String& String::operator=(const char *pstr){
    String temp(pstr);  // 利用构造函数创建临时对象
    *this = temp;       // 赋值运算重载
    return *this;
}

String& String::operator+=(const String & rhs){
    return append(rhs);
}

String& String::operator+=(const char *pstr){
    return append(pstr);
}

String operator+(const String &lhs, const String &rhs){
    String temp = lhs;
    temp += rhs;
    return temp;
}

String operator+(const String &lhs, const char *rhs){
    return lhs + String(rhs);   // 注意此处不写string会递归调用自身
}
String operator+(const char *lhs, const String &rhs){
    return String(lhs) + rhs;
}

char& String::operator[](std::size_t index){
    if(index >= strlen(_pstr)){
        static char nullchar = '\0';
        return nullchar;
    }
    return _pstr[index];
}

const char& String::operator[](std::size_t index) const{
    //return const_cast<String*>(this)->operator[](index);    // 强行去掉const，想想还是算了
    if(index >= strlen(_pstr)){
        static char nullchar = '\0';
        return nullchar;
    }
    return _pstr[index];
}

bool operator==(const String &lhs, const String &rhs){
    return strcmp(lhs.c_str(), rhs.c_str()) == 0; 
}

bool operator!=(const String &lhs, const String &rhs){
    return strcmp(lhs.c_str(), rhs.c_str()) != 0;
}

bool operator<(const String &lhs, const String &rhs){
    return strcmp(lhs.c_str(), rhs.c_str()) < 0;
}

bool operator>(const String &lhs, const String &rhs){
    return strcmp(lhs.c_str(), rhs.c_str()) > 0;
}

bool operator<=(const String &lhs, const String &rhs){
    return strcmp(lhs.c_str(), rhs.c_str()) < 0 || strcmp(lhs.c_str(), rhs.c_str()) == 0;
}

bool operator>=(const String &lhs, const String &rhs){
    return strcmp(lhs.c_str(), rhs.c_str()) > 0 || strcmp(lhs.c_str(), rhs.c_str()) == 0;
}

std::ostream &operator<<(std::ostream &os, const String &s){
    os << s._pstr;
    return os;
}

// 应当考虑的点：
// 1. 不可以直接使用is >> s._pstr，指针变量使用前必须初始化
// 2. 如果之前的s._pstr指向了某个对空间，那么还需要考虑是否会有内存泄漏
// 3. 首先判断当前指针是否指向了有效位置，如果有则回收该空间
// 4. 使用vector接收用户录入的字符数据（不确定用户究竟录入多少字符）
// 5. 申请堆空间，将vector里面的字符复制到堆空间中
// 6. 指针再去指向该堆空间
std::istream &operator>>(std::istream &is, String &s){
    // is >> s._pstr;
    // 可以以换行符作为用户录入数据结束的标志

    if(s._pstr){
        delete [] s._pstr;
    }

    vector<char> _input;
    char c;
    // 不加括号可能会先比较后复制，浪费一个字符的位置; EOF是结束标志
    while((c = is.get()) != '\n' && c != EOF && !is.fail()){  
        _input.push_back(c);
    }

//    char* temp = new char[_input.size() + 1]();
//    for(size_t i = 0; i < _input.size(); ++i){
//        temp[i] = _input[i];
//    }
//    s._pstr = temp;
    s._pstr = new char[_input.size() + 1];
    std::copy(_input.begin(), _input.end(), s._pstr);

    return is;
}

int main() {
    cout << "----- 测试1：基础构造 -----" << endl;
    String s1;                     // 默认构造
    cout << "s1.empty(): " << s1.empty() << endl;
    cout << "s1.size(): " << s1.size() << endl;

    cout << "\n----- 测试2：C字符串构造 -----" << endl;
    String s2("Hello");            // const char* 构造
    cout << "s2: " << s2.c_str() << endl;
    cout << "s2.size(): " << s2.size() << endl;

    cout << "\n----- 测试3：拷贝构造 -----" << endl;
    String s3(s2);                 // 拷贝构造
    cout << "s3: " << s3.c_str() << endl;

    cout << "\n----- 测试4：赋值运算符 -----" << endl;
    String s4;
    s4 = s3;                       // 赋值运算
    cout << "s4: " << s4.c_str() << endl;

    cout << "\n----- 测试5：append成员函数 -----" << endl;
    s4.append(" World");           // append(const char*)
    cout << "s4 after append: " << s4.c_str() << endl;

    String s5(" C++");
    s4.append(s5);                 // append(const String&)
    cout << "s4 after append: " << s4.c_str() << endl;

    cout << "\n----- 测试6：链式调用 -----" << endl;
    s4.append("!").append(" 2023"); // 链式调用
    cout << "s4 final: " << s4.c_str() << endl;

    cout << "\n----- 测试7：运算符重载 -----" << endl;
    String s6 = "apple";
    String s7 = "banana";
    String s8 = "apple";

    // 比较运算符
    cout << "s6 < s7: " << (s6 < s7) << " (expected: 1)" << endl;
    cout << "s6 == s8: " << (s6 == s8) << " (expected: 1)" << endl;
    cout << "s6 != s7: " << (s6 != s7) << " (expected: 1)" << endl;

    // 下标运算符
    s6[0] = 'A';  // 修改首字母
    cout << "s6 after modify: " << s6.c_str() << " (expected: Apple)" << endl;
    cout << "s6[1]: " << s6[1] << " (expected: p)" << endl;

    // 越界访问测试
    cout << "s6[100]: " << (s6[100] == '\0' ? "\\0" : "?") << " (expected: \\0)" << endl;

    cout << "\n----- 测试8：流操作符 -----" << endl;
    String s9;
    cout << "Enter a string (end with Enter): ";
    std::cin >> s9;  // 测试输入运算符
    cout << "You entered: " << s9 << endl;

    cout << "\n----- 测试9：复合运算符 -----" << endl;
    String s10 = "Hello";
    s10 += " C++";
    cout << "s10 += : " << s10 << " (expected: Hello C++)" << endl;

    String s11 = s10 + " World";
    cout << "s11 = s10 + \" World\": " << s11 << " (expected: Hello C++ World)" << endl;

    String s12 = "Prefix " + s11;
    cout << "s12 = \"Prefix \" + s11: " << s12 << endl;

    cout << "\n----- 测试10：极端情况 -----" << endl;
    String s13;  // 空字符串
    cout << "s13.empty(): " << s13.empty() << " (expected: 1)" << endl;
    s13 += "Now it's not empty";
    cout << "s13 after +=: " << s13 << " (size: " << s13.size() << ")" << endl;

    // 自赋值测试
    s13 = s13;
    cout << "After self-assignment: " << s13 << endl;

    cout << "\n----- 测试结束，析构调用 -----" << endl;
    return 0;
}

